package com.iou.view;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.iou.bean.IOUNote;
import com.iou.bean.IOUUser;
import com.iou.database.DatabaseHelper;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.ItemClickEvent.ItemClickListener;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.Label;
import com.vaadin.ui.OptionGroup;
import com.vaadin.ui.Panel;
import com.vaadin.ui.PopupDateField;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.BaseTheme;

/**
 * A view where the user's note list and filtering options are shown.
 */
@SuppressWarnings("serial")
public class ListView extends Panel implements View {

    /*
     * Class variables
     */
    private HorizontalSplitPanel split;
    private static IOUUser user;
    private static Table table;
    static List<IOUNote> noteList;
    private CheckBox IOUCheckBox;
    private CheckBox UOMeCheckBox;
    private CheckBox completedCheckBox;
    private OptionGroup amountFilterSelect;
    private OptionGroup dateFilterSelect;
    private TextField amount;
    private TextField participant;
    private PopupDateField date;

    private static final List<String> dateFilterType = Arrays
            .asList(new String[] { "Before", "After" });
    private static final List<String> amountFilterType = Arrays
            .asList(new String[] { "More than", "Less than" });

    /**
     * Constructor.
     * 
     * @param givenUser
     * @throws SQLException
     */
    public ListView(IOUUser givenUser) throws SQLException {

        this.user = givenUser;

        // Set the panel to cover the full browser window.
        setSizeFull();

        // Creating a split panel & setting it as the page content.
        initSplitPanel();

        // Left part of the split panel.
        try {
            initLeftSide();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // Right part of the split panel.
        initRightSide();
    }

    /**
     * This method handles the initialization of the split panel in the list
     * view.
     */
    public void initSplitPanel() {
        split = new HorizontalSplitPanel();
        setContent(split);
    }

    /**
     * This method handles the initialization of the left side of the list view.
     * 
     * @throws SQLException
     */
    @SuppressWarnings("deprecation")
    public void initLeftSide() throws SQLException {

        final VerticalLayout vasen = new VerticalLayout();
        vasen.setSizeFull();
        split.setFirstComponent(vasen);

        // IOU-table setup.
        table = new Table();
        vasen.addComponent(table);
        table.setSizeFull();
        table.setImmediate(true);
        table.setSelectable(true);

        table.addContainerProperty("Type", String.class, null);
        table.addContainerProperty("Amount", Double.class, null);
        table.addContainerProperty("Participant", String.class, null);
        table.addContainerProperty("Date", String.class, null);
        table.addContainerProperty("Status", String.class, null);

        /*
         * Double click listener for the table. Double click -> new InfoView
         */
        table.addListener(new ItemClickListener() {
            public void itemClick(ItemClickEvent event) {
                if (event.getButton() == ItemClickEvent.BUTTON_RIGHT) {
                }
                if (event.isDoubleClick() && (table.getValue() != null)) {
                    int nro = Integer.parseInt(table.getValue().toString()) - 1;
                    InfoView newInfoView = new InfoView(user, noteList.get(nro));
                    Integer.parseInt(table.getValue().toString());
                } else {
                }
                table.refreshRowCache();

            }
        });

    }

    /**
     * This method handles the initialization of the right side of the list
     * view.
     */
    public void initRightSide() {

        VerticalLayout oikeaBase = new VerticalLayout();
        oikeaBase.setSizeFull();

        split.setSecondComponent(oikeaBase);

        VerticalLayout oikeaYla = new VerticalLayout();
        oikeaYla.setWidth("100%");
        oikeaYla.setMargin(true);
        oikeaYla.setSpacing(true);

        HorizontalLayout oikeaAla = new HorizontalLayout();
        oikeaAla.setSizeFull();
        oikeaAla.setMargin(true);
        oikeaAla.setSpacing(true);

        oikeaBase.addComponent(oikeaYla);
        oikeaBase.addComponent(oikeaAla);

        HorizontalLayout oikeaStatus = new HorizontalLayout();
        oikeaStatus.setWidth("100%");
        oikeaStatus.setSpacing(true);
        oikeaYla.addComponent(oikeaStatus);

        HorizontalLayout oikeaCheckBox = new HorizontalLayout();
        oikeaCheckBox.setSpacing(true);
        oikeaYla.addComponent(oikeaCheckBox);

        HorizontalLayout oikeaDateField = new HorizontalLayout();
        oikeaDateField.setSpacing(true);

        HorizontalLayout oikeaAmountField = new HorizontalLayout();
        oikeaDateField.setSpacing(true);

        HorizontalLayout oikeaButtonField = new HorizontalLayout();
        oikeaButtonField.setSpacing(true);

        Label searchTools = new Label("Filter/search tools:");
        searchTools.setSizeUndefined();

        Label userName = new Label("Current user: " + this.user.getUsername());
        userName.setSizeUndefined();

        Button logout = new Button("Logout...");
        logout.setStyleName(BaseTheme.BUTTON_LINK);
        logout.addClickListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                UI.getCurrent().getNavigator().navigateTo("LoginView");
            }
        });

        IOUCheckBox = new CheckBox("IOU");
        IOUCheckBox.setValue(true);
        UOMeCheckBox = new CheckBox("UOMe");
        UOMeCheckBox.setValue(true);
        completedCheckBox = new CheckBox("Completed");
        completedCheckBox.setValue(true);
        amount = new TextField("Amount:");
        amount.setImmediate(true);
        participant = new TextField("Participant:");
        date = new PopupDateField("Date:", new Date(System.currentTimeMillis()));
        date.setDateFormat("d.M.yyyy");
        Button submitButton = new Button("Reset filters");
        submitButton.addClickListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                IOUCheckBox.setValue(true);
                UOMeCheckBox.setValue(true);
                completedCheckBox.setValue(true);
                amountFilterSelect.setValue("More than");
                dateFilterSelect.setValue("Before");
                amount.setValue("");
                participant.setValue("");
                date.setValue(new Date(System.currentTimeMillis()));
                refreshList();
                addToTable();

            }
        });

        /*
         * "New IOU" button.
         */
        Button newIOU = new Button("New IOU");
        newIOU.addClickListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                WindowView newIOU = new WindowView(user);
            }
        });

        /*
         * "Main Menu" button.
         */
        Button navButton = new Button("Main Menu");
        navButton.addClickListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                UI.getCurrent().getNavigator().navigateTo("MainMenuView");
            }
        });

        /*
         * "Apply filters" button.
         */
        Button testFilter = new Button("Apply filters");
        testFilter.addClickListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                refreshList();
                addToTable();
                filterCheckboxes();
                filterTextfields();
                addToTable();
            }
        });

        /*
         * Addition/alignment
         */

        dateFilterSelect = new OptionGroup("", dateFilterType);
        dateFilterSelect.setValue("Before");
        dateFilterSelect.setWidth("60px");

        amountFilterSelect = new OptionGroup("", amountFilterType);
        amountFilterSelect.setValue("More than");
        amountFilterSelect.setWidth("85px");

        oikeaStatus.addComponent(searchTools);
        oikeaStatus.setComponentAlignment(searchTools, Alignment.TOP_LEFT);

        oikeaStatus.addComponent(userName);
        oikeaStatus.setComponentAlignment(userName, Alignment.TOP_RIGHT);

        oikeaStatus.addComponent(logout);
        oikeaStatus.setComponentAlignment(logout, Alignment.TOP_RIGHT);

        oikeaCheckBox.addComponent(IOUCheckBox);
        oikeaCheckBox.setComponentAlignment(IOUCheckBox, Alignment.MIDDLE_LEFT);

        oikeaCheckBox.addComponent(UOMeCheckBox);
        oikeaCheckBox
                .setComponentAlignment(UOMeCheckBox, Alignment.MIDDLE_LEFT);

        oikeaCheckBox.addComponent(completedCheckBox);
        oikeaCheckBox.setComponentAlignment(completedCheckBox,
                Alignment.MIDDLE_LEFT);

        oikeaYla.addComponent(oikeaAmountField);
        oikeaAmountField.addComponent(amountFilterSelect);
        oikeaAmountField.addComponent(amount);
        oikeaAmountField.setComponentAlignment(amountFilterSelect,
                Alignment.MIDDLE_LEFT);
        oikeaAmountField.setComponentAlignment(amount, Alignment.MIDDLE_LEFT);

        oikeaYla.addComponent(participant);
        oikeaYla.setComponentAlignment(participant, Alignment.MIDDLE_LEFT);

        oikeaYla.addComponent(oikeaDateField);
        oikeaDateField.addComponent(dateFilterSelect);
        oikeaDateField.addComponent(date);
        oikeaDateField.setComponentAlignment(dateFilterSelect,
                Alignment.MIDDLE_LEFT);
        oikeaDateField.setComponentAlignment(date, Alignment.MIDDLE_LEFT);

        oikeaYla.addComponent(oikeaButtonField);

        oikeaButtonField.addComponent(testFilter);
        oikeaButtonField.setComponentAlignment(testFilter,
                Alignment.MIDDLE_LEFT);

        oikeaButtonField.addComponent(submitButton);
        oikeaButtonField.setComponentAlignment(submitButton,
                Alignment.MIDDLE_LEFT);

        oikeaYla.addComponent(newIOU);
        oikeaYla.setComponentAlignment(newIOU, Alignment.MIDDLE_LEFT);

        oikeaAla.addComponent(navButton);
        oikeaAla.setComponentAlignment(navButton, Alignment.BOTTOM_RIGHT);

    }

    @Override
    public void enter(ViewChangeEvent event) {
    }

    /**
     * Adds all users notes to a table
     */
    public static void addToTable() {
        int counter = 1;
        table.removeAllItems();
        for (int i = 0; i < noteList.size(); i++, counter++) {
            table.addItem(new Object[] { noteList.get(i).getType(),
                    new Double(noteList.get(i).getAmount()),
                    noteList.get(i).getParticipant(),
                    noteList.get(i).getDate(),
                    noteList.get(i).getStatusString() }, new Integer(counter));
        }

    }

    /*
     * Adds all user's notes to the noteList.
     */
    public static void refreshList() {
        Map<String, Object> fieldValues = new HashMap<String, Object>();
        fieldValues.put("user_id", user.getUsername());
        try {
            noteList = DatabaseHelper.noteDao.queryForFieldValues(fieldValues);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /*
     * Checks IOU, UOMe and Completed checkboxes and removes filtered values
     * from the list.
     */
    public void filterCheckboxes() {
        /*
         * IOU filter (if the checkbox is not selected):
         */
        if (IOUCheckBox.getValue() == false) {
            // Remove all the IOUs from the list:
            for (int i = 0; i < noteList.size(); i++) {
                if (noteList.get(i).getType() == "IOU") {
                    noteList.remove(i);
                    i--;
                }
            }
        }

        /*
         * IOUMe filter (if the checkbox is not selected):
         */
        if (UOMeCheckBox.getValue() == false) {
            // Remove all the IOUMes from the list:
            for (int i = 0; i < noteList.size(); i++) {
                if (noteList.get(i).getType() == "UOMe") {
                    noteList.remove(i);
                    i--;
                }
            }
        }

        /*
         * Complete filter (if the chekbox is not selected):
         */
        if (completedCheckBox.getValue() == false) {
            // Remove all completed notes from the list:
            for (int i = 0; i < noteList.size(); i++) {
                if (noteList.get(i).getStatus() == true) {
                    noteList.remove(i);
                    i--;
                }
            }
        }
    }

    /*
     * Checks "Amount" and "Participant" textFields and "Date" PopupDatefield
     * and removes filtered values from the list
     */
    @SuppressWarnings({ "deprecation" })
    public void filterTextfields() {

        /*
         * Amount filter:
         */
        double filterAmount;
        try {
            filterAmount = Double.parseDouble(amount.getValue());
            if (amount.getValue().isEmpty() == false) {
                if (amountFilterSelect.getValue() == "More than") {
                    /*
                     * If "More Than" is selected, this removes all notes below
                     * the amount.
                     */
                    for (int i = 0; i < noteList.size(); i++) {
                        if (noteList.get(i).getAmount() < filterAmount) {
                            noteList.remove(i);
                            i--;
                        }
                    }
                } else {
                    /*
                     * If "Less than" is selected, this removes all notes above
                     * the amount.
                     */
                    for (int i = 0; i < noteList.size(); i++) {
                        if (noteList.get(i).getAmount() > filterAmount) {
                            noteList.remove(i);
                            i--;
                        }
                    }

                }
            }
        } catch (NumberFormatException e) {
            // If there's an invalid value on amount field, nothing is filtered
            // and no error message is shown to the user.
        }

        /*
         * Participant filter:
         */
        if (participant.getValue().isEmpty() == false) {
            // Remove all the notes that doesn't match:
            for (int i = 0; i < noteList.size(); i++) {
                if (participant.getValue().matches(
                        (noteList.get(i).getParticipant())) == false) {
                    noteList.remove(i);
                    i--;
                }
            }
        }

        /*
         * Date filter:
         */
        if (date.getValue() != null) {
            Date listaDate;
            if (dateFilterSelect.getValue() == "Before") {
                /*
                 * If "Before" is selected, this removes all the notes dated
                 * after the selected date.
                 */
                for (int i = 0; i < noteList.size(); i++) {
                    listaDate = new Date((noteList.get(i).getYear() - 1900),
                            (noteList.get(i).getMonth() - 1), noteList.get(i)
                                    .getDay());
                    if (listaDate.after(date.getValue())) {
                        noteList.remove(i);
                        i--;
                    }
                }

            } else {
                /*
                 * If "After" is selected, this removes all the notes dated
                 * before or at the selected date.
                 */
                for (int i = 0; i < noteList.size(); i++) {
                    listaDate = new Date((noteList.get(i).getYear() - 1900),
                            (noteList.get(i).getMonth() - 1), noteList.get(i)
                                    .getDay());
                    if (listaDate.before(date.getValue())) {
                        noteList.remove(i);
                        i--;
                    }
                }
            }
        }

    }
}
